package com.jdd.modules.sdk.sdkcall;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jdd.common.api.vo.Result;
import com.jdd.common.constant.CacheConstant;
import com.jdd.common.constant.JddConstant;
import com.jdd.common.util.CacheUtil;
import com.jdd.common.util.LedControlUtils;
import com.jdd.common.util.SnowFlakeUtil;
import com.jdd.modules.parking.entity.ConfigParkInfo;
import com.jdd.modules.parking.entity.ParkArmInfo;
import com.jdd.modules.parking.mapper.ParkArmInfoMapper;
import com.jdd.modules.parking.mapper.ParkCarEnterLogMapper;
import com.jdd.modules.parking.mapper.ParkCarOutLogMapper;
import com.jdd.modules.parking.service.IConfigParkInfoService;
import com.jdd.modules.parking.service.IParkArmInfoService;
import com.jdd.modules.sdk.SdkCallInterface;
import com.jdd.modules.sdk.config.CameraSdk;
import com.jdd.modules.sdk.sdkidentifycallbackresults.QianYiSdkIdentifyCallbackResults;
import com.jdd.modules.sdk.utils.*;
import com.jdd.modules.sdkopengatelog.entity.SdkOpenGateLog;
import com.jdd.modules.sdkopengatelog.service.ISdkOpenGateLogService;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;

/**
 * @version 1.0
 * @Description:
 * @author： jdd尚岳
 * @Date: 2021-08-06 15:53
 */
@Slf4j
@Component
public class QianYiSdkCallInterface extends SdkCallInterface {
    @Resource
    CameraSdk cameraSdk;
    @Resource
    private CacheUtil cacheUtill;
    @Resource
    private ParkArmInfoMapper parkArmInfoMapper;
    @Resource
    private QianYiSdkIdentifyCallbackResults qianYiSdkIdentifyCallbackResults;
    @Resource
    private ISdkOpenGateLogService openGateLogService;
    @Resource
    private IParkArmInfoService parkArmInfoService;
    @Resource
    private IConfigParkInfoService configParkInfoService;
    @Resource
    private ParkCarEnterLogMapper parkCarEnterLogMapper;
    @Resource
    private ParkCarOutLogMapper parkCarOutLogMapper;
    @Resource
    private ISdkOpenGateLogService sdkOpenGateLogService;

    @Override
    public Result SdkUnfold(String serialNo) {

        try {
            if (StringUtils.isBlank(serialNo)) {
                return Result.error("设备序列号不能为空!");
            }
            String handle = cacheUtill.get(CacheConstant.SDK_HANDLE, serialNo);
            if (StringUtils.isBlank(handle)) {
                return Result.error("请对设备进行初始化");
            }
            //开闸操作
            QIANYISDK.T_ControlGate.ByReference byReference = new QIANYISDK.T_ControlGate.ByReference();
            byReference.ucState = 1;
            int i = cameraSdk.qianYiSdk.Net_GateSetup(Integer.parseInt(handle), byReference);
            //开闸操作记录
            LambdaQueryWrapper<ParkArmInfo> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.eq(ParkArmInfo::getSerialNo, serialNo);
            ParkArmInfo parkArmInfo = parkArmInfoMapper.selectOne(queryWrapper);

            SdkOpenGateLog openGateLog = new SdkOpenGateLog();
            BeanUtils.copyProperties(parkArmInfo, openGateLog);
            openGateLog.setCreateTime(new Date());
            openGateLog.setId(SnowFlakeUtil.getId());
            openGateLog.setStateCode(i);
            openGateLog.setSwichType("0");
            openGateLogService.save(openGateLog);

            if (i != 0) {
                return Result.error("开闸失败");
            }
        } catch (Exception e) {
            log.error("sdk工具类:通过io进行开闸->{}", e);
        }
        return Result.ok().success("开闸成功");
    }

    @Override
    public Result SdkUnfold(String swichType, String serialNo, String plateNo) {

        try {
            if (StringUtils.isBlank(serialNo)) {
                return Result.error("设备序列号不能为空!");
            }
            String handle = cacheUtill.get(CacheConstant.SDK_HANDLE, serialNo);
            if (StringUtils.isBlank(handle)) {
                return Result.error("请对设备进行初始化");
            }
            //开闸操作
            QIANYISDK.T_ControlGate.ByReference byReference = new QIANYISDK.T_ControlGate.ByReference();
            byReference.ucState = 1;
            int i = cameraSdk.getQianYiSdk().Net_GateSetup(Integer.parseInt(handle), byReference);
            //开闸操作记录
            LambdaQueryWrapper<ParkArmInfo> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.eq(ParkArmInfo::getSerialNo, serialNo);
            ParkArmInfo parkArmInfo = parkArmInfoMapper.selectOne(queryWrapper);
            //出入口id
            String carId;
            //0进口，1出口
            if(JddConstant.StringNumber.STRING_ZERO.equals(parkArmInfo.getArmType())){
                carId = parkCarEnterLogMapper.findIdBySerialAndPlate(serialNo, plateNo);
            }else{
                carId = parkCarOutLogMapper.findIdBySerialAndPlate(serialNo, plateNo);
            }
            SdkOpenGateLog openGateLog = new SdkOpenGateLog();
            BeanUtils.copyProperties(parkArmInfo, openGateLog);
            openGateLog.setId(SnowFlakeUtil.getId());
            openGateLog.setCreateTime(new Date());
            openGateLog.setPlateNo(plateNo);
            openGateLog.setStateCode(i);
            openGateLog.setSwichType(swichType);
            openGateLog.setCapPlace(carId);
            sdkOpenGateLogService.save(openGateLog);

            if (i != 0) {
                return Result.error("开闸失败");
            }
        } catch (Exception e) {
            log.error("sdk工具类:通过io进行开闸->{}", e);
        }
        return Result.ok().success("开闸成功");
    }

    @Override
    public Result CameraSdkInit(String ip) {
        try {
            if (StringUtils.isBlank(ip)) {
                return Result.error("设备IP不能为空!");
            }
            //如果先前已经初始化相机，就不再初始化
            ParkArmInfo parkArmInfoByIp = parkArmInfoService.findParkArmInfoByIp(ip);
            if(null==parkArmInfoByIp){
                return Result.error("查找不到设备信息");
            }
            short a = 0;
            short b = 3;
            String serialNo = parkArmInfoByIp.getSerialNo();

            int handle = cameraSdk.getQianYiSdk().Net_AddCamera(ip);
            //链接句柄的相机
            if (cameraSdk.getQianYiSdk().Net_ConnCamera(handle, a, b) != 0) {
                log.error("初始化中获取设备句柄失败: ip->{}", ip);
                return Result.error("初始化链接句柄相机异常");
            }
            log.info("========获取设备句柄========：handle->{}", handle);
            if (handle < 0) {
                log.error("初始化中获取设备句柄失败: ip->{}", ip);
                return Result.error(ip + ":初始化中获取设备句柄失败");
            }
            //如果链接成功则放入句柄
            cacheUtill.put(CacheConstant.SDK_HANDLE, serialNo, handle);
            //开始监控
            int callbackindex = cameraSdk.getQianYiSdk().Net_RegImageRecvEx(handle, qianYiSdkIdentifyCallbackResults, Pointer.NULL);
            if (callbackindex != 0) {
                log.error("回调结果初始化失败: ip->{}", ip);
                return Result.error(ip + ":回调结果初始化失败");
            }
        } catch (Exception e) {
            log.error("sdk工具类:设备初始化方法—>{}", e);
        }
        log.info("设备初始化成功:ip->{}", ip);
        return Result.ok("初始化成功");
    }

    /**
     * LED屏幕发送语音播报方法
     *
     * @param serialNo
     * @param str
     * @return com.jdd.common.api.vo.Result
     * @author jdd孙庆伟
     * @date 2021/8/19 10:02:35
     * @version 1.0
     */
    @Override
    public Result Sdk485VoiceCommunication(String serialNo, String str) {
        try {
            if (StringUtils.isBlank(serialNo)) {
                return Result.error("设备序列号不能为空!");
            }
            String handle = cacheUtill.get(CacheConstant.SDK_HANDLE, serialNo);
            if (StringUtils.isBlank(handle)) {
                return Result.error("请对设备进行初始化");
            }
            //开启透明通道
            int i = Integer.parseInt(handle);
            byte[] data = null;
            ConfigParkInfo configParkInfo = getConfigParkInfo();
            if (JddConstant.CameraControl.CONTROLPANEL_FANGKONG.equals(configParkInfo.getControlPanelType())) {
                data = LedControlUtils.ledPlayVoice(str.trim());
            }
            if (JddConstant.CameraControl.CONTROLPANEL_FEILIDE.equals(configParkInfo.getControlPanelType())) {
                data = FeiLiDeLedUtils.sdKUnkledSpeech(str.trim());
            }
            if (JddConstant.CameraControl.CONTROLPANEL_QIANYI.equals(configParkInfo.getControlPanelType())) {
                data = QianYiLedUtils.sdKUnkledSpeech(str.trim());
            }
            if(JddConstant.CameraControl.CONTROLPANEL_QIXIE.equals(configParkInfo.getControlPanelType())){
                data= QiXieLedUtils.sdKUnkledSpeech(str.trim());
            }
            if(JddConstant.CameraControl.CONTROLPANEL_SMALL_FANGKONG.equals(configParkInfo.getControlPanelType())){
                data= SmallFangKongLedUtils.ledPlayVoice(str.trim());
            }
            if(JddConstant.CameraControl.CONTROLPANEL_ANKUAI.equals(configParkInfo.getControlPanelType())){
                data= AnKuaiLedUtils.sdKUnkledSpeech(str.trim());
            }
            QIANYISDK.T_RS485Data.ByReference rs485 = new QIANYISDK.T_RS485Data.ByReference();
            rs485.rs485Id = (byte) 0;
            int len = data.length;
            rs485.dataLen = (short) len;
            rs485.data = data;
            int ret = cameraSdk.getQianYiSdk().Net_SendRS485Data(Integer.parseInt(handle), rs485);
            if (ret != 0) {
                return Result.error("发送失败!");
            }

        } catch (Exception e) {
            log.error("sdk工具类:LED屏幕发送语音播报方法—>{}", e);
        }
        return Result.ok().success("成功");
    }

    /**
     * LED屏幕发送文字临时播放信息方法
     *
     * @param serialNo
     * @param str
     * @param like
     * @return com.jdd.common.api.vo.Result
     * @author jdd孙庆伟
     * @date 2021/8/19 10:02:22
     * @version 1.0
     */
    @Override
    public Result Sdk485TestContentCommunication(String serialNo, String str, String like) {
        try {
            if (StringUtils.isBlank(serialNo)) {
                return Result.error("设备序列号不能为空!");
            }
            String handle = cacheUtill.get(CacheConstant.SDK_HANDLE, serialNo);
            if (StringUtils.isBlank(handle)) {
                return Result.error("请对设备进行初始化");
            }
            //开启透明通道
            int i = Integer.parseInt(handle);
            byte[] data = null;
            ConfigParkInfo configParkInfo = getConfigParkInfo();
            if (JddConstant.CameraControl.CONTROLPANEL_FANGKONG.equals(configParkInfo.getControlPanelType())) {
                data = LedControlUtils.ledScreenShowAgreement(str.trim(), like);
            }
            if (JddConstant.CameraControl.CONTROLPANEL_FEILIDE.equals(configParkInfo.getControlPanelType())) {
                data = FeiLiDeLedUtils.ledTemporaryDisplay(str.trim(), like);
            }
            if (JddConstant.CameraControl.CONTROLPANEL_QIANYI.equals(configParkInfo.getControlPanelType())) {
                data = QianYiLedUtils.ledTemporaryDisplay(str.trim(), like);
            }
            if(JddConstant.CameraControl.CONTROLPANEL_QIXIE.equals(configParkInfo.getControlPanelType())){
                data= QiXieLedUtils.ledTemporaryDisplay(str.trim(),like);
            }
            if(JddConstant.CameraControl.CONTROLPANEL_SMALL_FANGKONG.equals(configParkInfo.getControlPanelType())){
                data= SmallFangKongLedUtils.ledScreenShowAgreement(str.trim(),like);
            }
            if(JddConstant.CameraControl.CONTROLPANEL_ANKUAI.equals(configParkInfo.getControlPanelType())){
                data= AnKuaiLedUtils.ledTemporaryDisplay(str.trim(),like);
            }
            QIANYISDK.T_RS485Data.ByReference rs485 = new QIANYISDK.T_RS485Data.ByReference();
            rs485.rs485Id = (byte) 0;
            int len = data.length;
            rs485.dataLen = (short) len;
            rs485.data = data;
            int ret = cameraSdk.qianYiSdk.Net_SendRS485Data(Integer.parseInt(handle), rs485);
            if (ret != 0) {
                return Result.error("发送失败!");
            }

        } catch (Exception e) {
            log.error("sdk工具类:LED屏幕发送文字临时播放信息方法—>{}", e);
        }

        return Result.ok().success("成功");
    }

    @Override
    public Result GetIsConnect(String serialNo) {
        try {
            if (StringUtils.isBlank(serialNo)) {
                return Result.error("设备序列号不能为空!");
            }
            String handle = cacheUtill.get(CacheConstant.SDK_HANDLE, serialNo);
            if (StringUtils.isBlank(handle)) {
                return Result.error("请对设备进行初始化");
            }
            //检查链接情况
            int i = cameraSdk.qianYiSdk.Net_QueryConnState(Integer.parseInt(handle));
            if (i != 0) {
                return Result.error("检查连接时异常");
            }
        } catch (Exception e) {
            log.error("sdk工具类:查询设备在线接口->{}", e);
        }
        return Result.ok().success("连接成功");
    }

    /**
     * 软触发
     *
     * @param serialNo
     * @return com.jdd.common.api.vo.Result
     * @author jdd孙庆伟
     * @date 2021/8/30 17:36:54
     * @version 1.0
     */
    @Override
    public Result TriggerExt(String serialNo) {
        try {
            if (StringUtils.isBlank(serialNo)) {
                return Result.error("设备序列号不能为空!");
            }
            String handle = cacheUtill.get(CacheConstant.SDK_HANDLE, serialNo);
            if (StringUtils.isBlank(handle)) {
                return Result.error("请对设备进行初始化");
            }
            QIANYISDK.T_RS485Data.ByReference ptImageSnap = new QIANYISDK.T_RS485Data.ByReference();
            int callbackindex = cameraSdk.getQianYiSdk().Net_ImageSnap(Integer.parseInt(handle), ptImageSnap);
            if (callbackindex != 0) {
                return Result.error("重新识别失败");
            }
        } catch (Exception e) {
            log.error("sdk工具类:软触发接口->{}", e);
        }
        return Result.ok().success("重新识别成功");
    }
    /*** 功能描述: 同步菲力德的时间
     * @param serialNo 序列号
     * @Author: lcy
     * @Date: 2022/1/4
     */
    public Result Sdk485Calibration(String serialNo){
        if (org.apache.commons.lang.StringUtils.isBlank(serialNo)) {
            return  Result.error("设备序列号不能为空!");
        }
        String handle = cacheUtill.get(CacheConstant.SERIAL_HANDLE, serialNo);
        if (org.apache.commons.lang.StringUtils.isBlank(handle)) {
            return   Result.error("请对设备进行初始化");
        }
        try {
            //开启透明通道
            int i = Integer.parseInt(handle);
            byte[] data = null;
            ConfigParkInfo configParkInfo = getConfigParkInfo();
            if (JddConstant.CameraControl.CONTROLPANEL_FEILIDE.equals(configParkInfo.getControlPanelType())) {
                data = FeiLiDeLedUtils.calibrationTime();
            }else{
                log.info("------当前系统控制板不是菲力德,无需同步----");
                return Result.error("无需同步");
            }
            int ret = cameraSdk.zhenshiSdk.VzLPRClient_SerialSend(i, data, data.length);
            if (ret != 0) {
                return  Result.error("同步失败!");
            }
        } catch (Exception e) {
            log.error("sdk工具类:同步时间—>{}", e);
        }
        return Result.ok().success("成功");
    }
    /**
     *  空闲状态指令
     *  方控：发送广告指令
     *  菲利德：进行内容存储
     * @param str
     * @return
     * @author renshangyi
     * @date 2022/1/26
     */
    @Override
    public Result Sdk485LedAdvertising(String serialNo, String str, String like) {
        String handle = cacheUtill.get(CacheConstant.SERIAL_HANDLE, serialNo);
        if (org.apache.commons.lang.StringUtils.isBlank(handle)) {
            return Result.error("请对设备进行初始化");
        }
        //开启透明通道
        int i = Integer.parseInt(handle);
        try {
            byte[] data = null;
            ConfigParkInfo configParkInfo = getConfigParkInfo();
            if (JddConstant.CameraControl.CONTROLPANEL_FANGKONG.equals(configParkInfo.getControlPanelType())) {
                data = LedControlUtils.ledScreenShowPermanent(str.trim(), like);
            }
            if (JddConstant.CameraControl.CONTROLPANEL_FEILIDE.equals(configParkInfo.getControlPanelType())) {
                data = FeiLiDeLedUtils.ledDownloadText(str.trim(), like);
            }
            if (JddConstant.CameraControl.CONTROLPANEL_SMALL_FANGKONG.equals(configParkInfo.getControlPanelType())) {
                data = LedControlUtils.ledScreenShowPermanent(str.trim(), like);
            }
            int ret = cameraSdk.zhenshiSdk.VzLPRClient_SerialSend(i, data, data.length);
            if (ret != 0) {
                return Result.error("发送失败!");
            }
        } catch (Exception e) {
            log.error("sdk工具类:LED屏幕发送文字临时播放信息方法—>{}", e);
        }
        return Result.ok().success("成功");
    }

    /**
     *  方控：修改日期显示位置
     * @param   serialNo
     * @return
     * @author renshangyi
     * @date 2022/1/26
     */
    @Override
    public Result Sdk485LedModifyDatePosition(String serialNo,String order) {
        String handle = cacheUtill.get(CacheConstant.SERIAL_HANDLE, serialNo);
        if (org.apache.commons.lang.StringUtils.isBlank(handle)) {
            return Result.error("请对设备进行初始化");
        }
        //开启透明通道
        int i = Integer.parseInt(handle);
        try {
            byte[] data = null;
            ConfigParkInfo configParkInfo = getConfigParkInfo();
            if (JddConstant.CameraControl.CONTROLPANEL_FANGKONG.equals(configParkInfo.getControlPanelType())) {
                data = LedControlUtils.hexToByteArray(order);
            }else{
                log.info("------当前系统控制板不是方控,不能修改日期位置----");
                return Result.error("无法修改");
            }
            int ret = cameraSdk.zhenshiSdk.VzLPRClient_SerialSend(i, data, data.length);
            if (ret != 0) {
                return Result.error("发送失败!");
            }
        } catch (Exception e) {
            log.error("sdk工具类:LED屏幕发送文字临时播放信息方法—>{}", e);
        }
        return Result.ok().success("成功");
    }
    /**
     * @author lcy
     * @date 2021/8/13
     * @Description 拿到当前相机
     */
    private ConfigParkInfo getConfigParkInfo() {
        //这里不作null判断，调用的方法做判断
        return configParkInfoService.findConfigParkInfoByParkCode();
    }

}
